#pragma once

// Vector2_t
// (Thomas Rippon) Represents a 2-dimensional euclidean vector
namespace Core {
	template<class T>
	class Vector2_t {
	public: // Typedefs
		typedef T value_type;
		typedef Vector2_t<T> this_type;

	public: // Constructors
		Vector2_t();
		Vector2_t( T x, T y );

		// Conversion to other type of vector (no implicit conversion)
		template<class U>
		explicit Vector2_t( const Vector2_t<U>& vec ) : x(vec.x), y(vec.y) { }

	public: // Named constructors
		static this_type fromAngle( T angle, T length ); // Doesn't make sense for integral types

	public: // Operators
		const this_type operator - () const;
		const this_type operator + ( const this_type& vec ) const;
		const this_type operator - ( const this_type& vec ) const;
		const this_type operator * ( const this_type& vec ) const;
		const this_type operator / ( const this_type& vec ) const;
		const this_type operator * ( T scalar ) const;
		const this_type operator / ( T scalar ) const;

		this_type& operator += ( const this_type& vec );
		this_type& operator -= ( const this_type& vec );
		this_type& operator *= ( const this_type& vec );
		this_type& operator /= ( const this_type& vec );
		this_type& operator *= ( T scalar );
		this_type& operator /= ( T scalar );

	public: // Comparison Operators
		bool operator == ( const this_type& vec ) const;
		bool operator != ( const this_type& vec ) const;
		bool operator < ( const this_type& vec ) const;

	public: // Methods
		T dot( const this_type& vec ) const;
		T sqLength() const;
		T length() const;
		this_type& normalize();
		const this_type normalized() const;
		const this_type rhNormal() const;
		const this_type lhNormal() const;
		const this_type projectionOnto( const this_type& vec ) const;
		const T projectionLength( const this_type& vec ) const;
		const this_type reflected( const this_type& normal ) const;
		const T angle( const this_type& vec ) const;

	public: // Accessors
		T& operator[] ( int idx );
		const T& operator[] ( int idx ) const;

	private: // Helper members
		static T Vector2_t::* const (map[2]);

	public: // Members
		T x, y;
	};

	// Typedefs available to the Core namespace
	typedef Vector2_t<int> Vector2i;
	typedef Vector2_t<double> Vector2;
	typedef Vector2_t<float> Vector2f;
}